﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AddIn.EA.Framework;
using AddIn.EA.Architecture.CatalogService.BusinessEntity;
using System.Xml;
using AddIn.EA.Architecture.Validation.BusinessEntity;

namespace AddIn.EA.Architecture.CatalogService.BusinessLogic
{
    public class InterfaceXml
    {
        private RepositoryManager repository { get; set; }
        private Package service { get; set; }

        public InterfaceXml(RepositoryManager repository, Package service)
        {
            this.repository = repository;
            this.service = service;
        }

        /// <summary>
        /// Gera os XMLs das interfaces de contrato de servico
        /// </summary>
        /// <param name="fileConfig"></param>
        /// <returns></returns>
        public List<MemberBase> GetInterfaceXmls(string fileConfig)
        {
            var interfaceElements = GetInterfaceElements();
            var interfaceXmls = new List<MemberBase>();

            // Percorrer as interfaces do servico
            foreach (var interfaceElement in interfaceElements)
            {
                var listItem = new List<Item>();

                // Buscar os protocolos do arquivo de config
                var config = new XmlDocument();
                config.Load(fileConfig);
                var configBaseAddress = 
                    config.SelectNodes(
                    string.Format("/configuration/system.serviceModel/services/service/endpoint[@contract=\"{0}\"]/../host/baseAddresses/add/@baseAddress",
                    interfaceElement.GetFullName()));

                // Adicionar os protocolos
                if (configBaseAddress != null && configBaseAddress.Count > 0)
                {
                    foreach (XmlAttribute baseAddress in configBaseAddress)
                    {
                        string protocolName = string.Empty;
                        if (baseAddress.Value.StartsWith("net.tcp"))
                            protocolName = "Tcp";
                        if (baseAddress.Value.StartsWith("net.pipe"))
                            protocolName = "NamedPipe";

                        listItem.Add(new Item
                        {
                            Term = new List<string> { protocolName },
                            Description = baseAddress.Value
                        });
                    }
                    listItem = listItem.OrderByDescending(x => x.Term[0]).ToList();
                }
                else
                    throw new CatalogServiceException("Protocolos não encontrados no config " + fileConfig);

                // Adicionar a interface
                var member = new MemberType()
                {
                    ProjectGUID = this.repository.ProjectGUID,
                    Name = interfaceElement.GetFullName(),
                    Summary = interfaceElement.Notes,
                    Remarks = new Remarks
                    {
                        List = new ListBullet
                        {
                            Item = new List<Item>
                            {
                                new Item
                                {
                                    Description = "Url´s de acesso ao contrato",
                                    List = new ListTable
                                    {
                                        ListHeader = new Item
                                        {
                                            Term = new List<string> { "Protocolo" },
                                            Description = "URL"
                                        },
                                        Item = listItem
                                    }
                                }
                            }
                        }
                    }
                };
                interfaceXmls.Add(member);
            }

            return interfaceXmls;
        }

        /// <summary>
        /// Retorna os elementos das interfaces
        /// </summary>
        /// <returns></returns>
        public List<Element> GetInterfaceElements()
        {
            var interfaceElements =
                (from el in this.service.GetPackageByName("ServiceContract").Elements
                 where el.Type == ElementType.Interface &&
                     el.Stereotype == "ServiceContract"
                 select el).ToList();

            return interfaceElements;
        }

    }
}
